COLLATION MODULE
================

Standard: UTS #10 (Unicode Collation Algorithm)
Files:    src/lingenic_text-collation_spec.ads   (ghost specification)
          src/lingenic_text-collation.ads        (public API)
          src/lingenic_text-collation.adb        (implementation)


PURPOSE
-------

The Collation module implements the Unicode Collation Algorithm using
the Default Unicode Collation Element Table (DUCET).  It provides
linguistically correct string comparison and sort key generation.


GHOST SPECIFICATION (Collation_Spec)
------------------------------------

Types:

  subtype Weight_16 is Natural range 0 .. 65535;
    16-bit collation weight.

  type Collation_Element is record
    Primary   : Weight_16;
    Secondary : Weight_16;
    Tertiary  : Weight_16;
    Variable  : Boolean;
  end record;

  type Variable_Weight_Option is (Non_Ignorable, Shifted);
    Non_Ignorable: variable-weight elements retain their weights.
    Shifted: variable-weight elements are shifted to a quaternary level.

  type Comparison_Result is (Less, Equal, Greater);

Implicit Weight Ranges (UTS #10, Section 10.1.3, Unicode 17.0):

  For codepoints not in the DUCET, implicit weights are computed
  algorithmically based on the codepoint's block:

  Core Han:   U+4E00..U+9FFF (CJK Unified Ideographs) and specific
              ranges in CJK_Compatibility_Ideographs
  Other Han:  CJK Extensions A through J
  Siniform:   Tangut, Tangut Components, Nushu, Khitan Small Script


INITIALIZATION
--------------

  procedure Initialize
    (UCD_Dir : String;
     Success : out Boolean);

    Pre:  Normalization.Initialized
    Post: if Success then Initialized

Reads from UCD_Dir:

  allkeys.txt    Default Unicode Collation Element Table (DUCET)
                 ~2.3 MB, contains collation elements for every
                 assigned codepoint plus contractions

Builds internal data tables:

  CE_Index/CE_Data          Per-codepoint collation element lookup
  Contraction_Starter       Boolean array: True if CP starts a contraction
  Starter_Index/Entries     Contraction matching tables
  Implicit_Ranges           @implicitweights ranges from allkeys.txt


PUBLIC API
----------

Compare:

  procedure Compare
    (Left    : Byte_Array;
     Right   : Byte_Array;
     Option  : Variable_Weight_Option;
     Result  : out Comparison_Result;
     Success : out Boolean);

    Pre:  Initialized, Normalization.Initialized,
          Normalization.Data_All_Terminal
          Left'Length >= 1, Right'Length >= 1
    Post: (none beyond Success semantics)

  Compares two UTF-8 strings using DUCET collation.

  Algorithm:
    1. Both inputs are NFD-normalized internally
    2. Collation elements are produced for each codepoint
       (including contraction handling and implicit weights)
    3. Multi-level comparison per UTS #10:
       - Level 1: Primary weights (base character differences)
       - Level 2: Secondary weights (accent differences)
       - Level 3: Tertiary weights (case differences)
       - Level 4: Quaternary weights (Shifted mode only)
    4. Result: Less, Equal, or Greater

  Variable weighting:
    Non_Ignorable: variable elements (punctuation, symbols) use their
    actual weights at all levels.
    Shifted: variable elements are ignored at levels 1-3, compared at
    a quaternary level (sorts punctuation as very low priority).

  Success is False if either input is invalid UTF-8, too long, or
  an internal buffer overflows.

Sort_Key:

  procedure Sort_Key
    (Input   : Byte_Array;
     Option  : Variable_Weight_Option;
     Key     : in out Byte_Array;
     Last    : out Natural;
     Success : out Boolean);

    Pre:  Initialized, Normalization.Initialized,
          Normalization.Data_All_Terminal
          Input'Length >= 1, Key'Length >= 1
    Post: if Success then
            Last in Key'First..Key'Last
          else
            Last = Key'First - 1

  Builds a binary sort key from a UTF-8 string.

  Sort keys can be compared byte-by-byte (like memcmp) for correct
  ordering.  This is useful when the same string must be compared
  against many others: compute the sort key once, then compare keys.

  The sort key format follows UTS #10: primary weights concatenated,
  then a separator, secondary weights, separator, tertiary weights,
  and (for Shifted mode) quaternary weights.


DEPENDENCIES
------------

The Collation module depends on:

  Normalization    NFD normalization of input strings
  Properties       (transitively, through Normalization)

Both must be initialized before Collation.Initialize is called.
Normalization must be initialized before Compare or Sort_Key is called
(enforced by preconditions requiring Normalization.Initialized and
Normalization.Data_All_Terminal).


CONTRACTION HANDLING
--------------------

Some collation elements span multiple codepoints (e.g., "ch" in some
languages).  The DUCET includes these as contractions.

The implementation uses:
  - Contraction_Starter: flat Boolean array indexed by codepoint.
    True if a codepoint can start a contraction sequence.
  - Starter_Index/Entries: for contraction starters, a table of
    possible continuations and their collation elements.

When a contraction starter is encountered, the algorithm attempts
longest-match against the continuation table.  If no match, the
single-codepoint CE is used.


IMPLICIT WEIGHTS
----------------

Codepoints not in the DUCET receive implicit weights computed from
their codepoint value.  The algorithm follows UTS #10 Section 10.1.3:

  - Classify the codepoint into a weight range (Core Han, Other Han,
    Siniform, or Unassigned)
  - Compute primary weight from the codepoint value using range-specific
    base values and offsets
  - Secondary and tertiary weights are fixed (0020h and 0002h)

This ensures all codepoints have a defined sort order even without
explicit DUCET entries.
